<template>
  <div
    v-if="isPreferences"
    class="theme-box-container display-flex flex-align flex-justify-between"
  >
    <div
      class="theme-box-item display-flex display-column flex-align"
      v-for="item in themeBoxList"
      :key="item.value"
      @click="handleChangeBoxTheme(item.value)"
    >
      <div
        class="box display-flex flex-align flex-justify outline"
        :class="[
          preferencesStore.appearance.theme.theme === item.value && 'is-active'
        ]"
      >
        <component :is="item.icon"></component>
      </div>
      <span class="text">{{ $t(item.text) }}</span>
    </div>
  </div>
  <div
    v-else
    class="theme-switcher-container display-flex flex-align flex-justify"
    @click="handleChangeTheme"
  >
    <core-light-theme-icon
      class="light-theme-icon"
      :class="preferencesStore.isDark && 'active-light'"
    ></core-light-theme-icon>
    <core-dark-theme-icon
      class="dark-theme-icon"
      :class="!preferencesStore.isDark && 'active-dark'"
    ></core-dark-theme-icon>
  </div>
</template>

<script setup lang="ts">
import { usePreferencesStore } from '@/stores'
import { nextTick } from 'vue'
import {
  CoreLightThemeIcon,
  CoreDarkThemeIcon,
  CoreSystemThemeIcon
} from '@/components/CoreIcon'
import type { Theme } from '@/stores/modules/preferences/types'

withDefaults(defineProps<{ isPreferences?: boolean }>(), {
  isPreferences: false
})

const preferencesStore = usePreferencesStore()

const themeBoxList = [
  { text: 'preferences.light', value: 'light', icon: CoreLightThemeIcon },
  { text: 'preferences.dark', value: 'dark', icon: CoreDarkThemeIcon },
  { text: 'preferences.system', value: 'system', icon: CoreSystemThemeIcon }
]

const handleChangeBoxTheme = (value: string) => {
  preferencesStore.setTheme(value as Theme)
}

const handleChangeTheme = async (e: MouseEvent) => {
  const canStartViewTransition =
    typeof document.startViewTransition === 'function' &&
    !window.matchMedia('(prefers-reduced-motion: reduce)').matches

  const handleSetTheme = () => {
    preferencesStore.setTheme(preferencesStore.isDark ? 'light' : 'dark')
  }

  if (!canStartViewTransition || !e) {
    handleSetTheme()
    return
  }

  const transition = document.startViewTransition(async () => {
    handleSetTheme()
    await nextTick()
  })

  await transition.ready

  const x = e.clientX
  const y = e.clientY

  const horizontalDistance = Math.max(x, innerWidth - x)
  const verticalDistance = Math.max(y, innerHeight - y)
  const radius = Math.hypot(horizontalDistance, verticalDistance)

  const clipPath = [
    `circle(0px at ${x}px ${y}px)`,
    `circle(${radius}px at ${x}px ${y}px)`
  ]

  const keyframes = {
    clipPath: preferencesStore.isDark ? [...clipPath].reverse() : clipPath
  }
  const options = {
    duration: 450,
    easing: 'ease-in',
    pseudoElement: preferencesStore.isDark
      ? '::view-transition-old(root)'
      : '::view-transition-new(root)'
  }
  document.documentElement.animate(keyframes, options)
}

defineOptions({
  name: 'CoreThemeSwitcher'
})
</script>

<style scoped lang="scss">
.theme-box-container {
  padding-bottom: 20px;

  .theme-box-item {
    width: 100px;
    cursor: pointer;

    .box {
      width: 100%;
      padding: 16px 4px;
      font-size: 20px;
      color: var(--core-text-color-05);
    }

    .text {
      margin-top: 8px;
      font-size: 12px;
      line-height: 16px;
      color: var(--core-text-color-06);
    }
  }
}

.theme-switcher-container {
  position: relative;
  width: var(--core-header-tools-size);
  height: var(--core-header-tools-size);
  color: var(--core-text-color-05);
  cursor: pointer;
  border-radius: 50%;
  transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);

  &:hover {
    color: var(--core-text-color-03);
    background-color: var(--core-bg-color-01);
  }

  .light-theme-icon,
  .dark-theme-icon {
    position: absolute;
  }

  .light-theme-icon {
    opacity: 0;
    transition:
      transform 1.6s cubic-bezier(0.5, 1.5, 0.75, 1.25),
      opacity 0.6s cubic-bezier(0.25, 0, 0.3, 1);
    transform: rotate(0);
  }

  .active-light {
    opacity: 1;
    transform: rotate(90deg);
  }

  .dark-theme-icon {
    opacity: 0;
    transition:
      transform 1.6s cubic-bezier(0.25, 0, 0.2, 1),
      opacity 0.6s cubic-bezier(0.25, 0, 0.3, 1);
    transform: rotateZ(0.2turn);
  }

  .active-dark {
    opacity: 1;
    transform: rotateZ(0);
  }
}
</style>
